﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Dynamics.BusinessConnectorNet;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using System.Security.Principal;
using PJ.Framework.Common;

namespace PJ.Framework.DynamicsAX
{
    public sealed class DynamicsAXBroker : IDisposable
    {
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public static AxaptaContainer CreateContainer()
        {
                return Instance.Axapta.CreateAxaptaContainer();
        }

        public static object StaticMethod(string className, string method)
        {
            return StaticMethod(className, method, null);
        }
        public static object StaticMethod(string className, string method, object argument)
        {
            return StaticMethod(className, method, new object[] { argument });
        }
        public static object StaticMethod(string className, string method, object argument1, object argument2)
        {
            return StaticMethod(className, method, new object[] { argument1, argument2});
        }
        public static object StaticMethod(string className, string method, object argument1, object argument2, object argument3)
        {
            return StaticMethod(className, method, new object[] {argument1, argument2, argument3});
        }
        public static object StaticMethod(string className, string method, object[] args)
        {
            using (ActivityTracer.Trace("DynamicsAX"))
            {
                string arguments = "";
                foreach (object arg in args)
                    if (arguments == null)
                        arguments = "" + args.ToString();
                    else
                        arguments += ", " + args.ToString();

                Logger.Write("Static method call " + className + "::" + method + "(" + arguments + ")");
                return Instance.Axapta.CallStaticClassMethod(className, method, args);
            }
        }

        private static DynamicsAXBroker Instance
        {
            get
            {
                return _Instance;
            }
        }
        private Axapta Axapta
        {
            get
            {
                if (_Axapta == null)
                {
                    _Axapta = new Axapta();
                    Open();
                }
                return _Axapta;
            }
        }
        private void Open()
        {
            using (ActivityTracer.Trace("DynamicsAX"))
            {
                try
                {
                    Logger.Write("Dynamics AX Business connector openning session on company : " + Properties.Settings.Default.DynamicsAXCompany
                                    + " User : " + WindowsIdentity.GetCurrent().Name);
                    _Axapta.Logon(Properties.Settings.Default.DynamicsAXCompany, "", "", "");
                }
                catch (Exception e)
                {
                    try
                    {
                        _Axapta.Dispose();
                    }
                    finally
                    {
                        _Axapta = null;
                    }
                    if (ExceptionPolicy.HandleException(e, "Logging Policy"))
                        throw;
                }
                _Axapta.Refresh();
                Logger.Write("Dynamics AX Business connector session openned. Id=" + _Axapta.Session());
            }
        }
        private void Close()
        {
            if (_Axapta != null)
            {
                using (ActivityTracer.Trace("DynamicsAX"))
                {
                    Logger.Write("Dynamics AX Business connector session closing");
                    _Axapta.Logoff();
                    Logger.Write("Dynamics AX Business connector session closed");
                }
            }
        }

        public bool Opened
        {
            get
            {
                if (_Axapta == null)
                    return false;
                return _Axapta.Session() != 0;
            }
            set
            {
                if (value && !Opened)
                    Open();
                if (!value && Opened)
                    Close();
            }
        }


        private void Dispose(bool disposable)
        {
            Close();
            if (_Axapta != null && disposable)
            {
                _Axapta.Dispose();
                _Axapta = null;
            }
        }

        private Axapta _Axapta;
        private static readonly DynamicsAXBroker _Instance = new DynamicsAXBroker();


    }
}
